<?php
/**
* 2016年7月21日 16:43:44
*/
class Token_model extends MY_Model
{
	
	function __construct()
	{
		parent::__construct();
		//加载curl工具模型
		$this->load->model('Curl_model','curl');
		//定义微信参数常量
  		$where = array('id' => 1);
  		$info = $this->hw_getRecord('info', $where, '*');
  		defined('APPID') or define('APPID', $info['appid']);
  		defined('APPSECRET') or define('APPSECRET', $info['appsecret']);
	}
	/**
	 * 从微信获取token
	 * @return [type] [description]
	 */
	function getToken(){
		$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.APPID.'&secret='.APPSECRET;
  		$token = $this->curl->_get($url);
  		return $token['access_token'];
	}
	/**
	 * 获取微信票据access_token总方法
	 * @return [type] [description]
	 */
	function getAccessToken(){
		//试图从数据库读取token
		$where = array('id' => 1);
		$data = $this->hw_getRecord('token', $where, '*');
		//如果查询结果为空，则通过微信获取access_token并写入数据库
		if( ($data == '') || ($data == null)){
			$token = $this->getToken();
			$insert = array(
				'access_token' => $token,
				'token_time' => time()+7000,
				'tokentime' => date("Y-m-d H:i:s", time()+7000),
				);
			$add_res = $this->hw_Insert('token',$insert);
			
			return $token;
		
		}elseif(($data['token_time']<=time())||($data['access_token'] == '')){
			//token过期 重新获取微信token并更新数据库token
			$token = $this->getToken();
			$update = array(
				'access_token' => $token,
				'token_time' => time()+7000,
				'tokentime' => date("Y-m-d H:i:s", time()+7000), 
				);
			$update_res = $this->hw_Update('token',$update,$where);
			
			return $token;
		
		}else{
			//直接返回数据库token
			return $data['access_token'];
		}
	}
	/**
	 * 获取微信js-sdk票据
	 * @param  [type] $token [description]
	 * @return [type]        [description]
	 */
	function getTicket($token){
		$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".$token;
		$result = $this->curl->_get($url);
		
		return $result;
	}
	/**
	 * 获取js-sdk票据总方法
	 * @return [type] [description]
	 */
	function getJsApiTicket(){
		//试图从数据库获取ticket
		$where = array('id'=>1);
		$data = $this->hw_getRecord('token', $where, '*');

		if( ($data == '') ||($data['ticket'] == '') || ($data == null) || ($data['ticket_time']<=time())){
			//ticket不存在获取过期都重新从微信获取 并更新数据库ticket
			$token = $this->getAccessToken();
			$res = $this->getTicket($token);
			
			$data = array(
				'ticket' => $res['ticket'],
				'ticket_time' => time()+7000,
				'tickettime' => date("Y-m-d H:i:s", time()+7000), 
				);
			$add_res = $this->hw_Update('token',$data,$where);
			return $res['ticket'];
		}else{
			//直接返回数据库ticket
			return $data['ticket'];
		}
	}
	/**
	 * 微信jssdk参数
	 * @return [type] [description]
	 */
	public function getSignPackage($url) {
		$jsapiTicket = $this->getJsApiTicket();
		// 注意 URL 一定要动态获取，不能 hardcode.
		$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";

		$timestamp = time()."";
		$nonceStr = $this->generateNonceStr();

		// 这里参数的顺序要按照 key 值 ASCII 码升序排序
		$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
		
		$signature = sha1($string);

		$signPackage = array(
		  "appId"     => APPID,
		  "nonceStr"  => $nonceStr,
		  "timestamp" => $timestamp,
		  "url"       => $url."/",
		  "signature" => $signature,
		  "rawString" => $string
		);
		return $signPackage; 
	}
	public function ajaxGetSignPackage($url) {
		$jsapiTicket = $this->getJsApiTicket();
		// 注意 URL 一定要动态获取，不能 hardcode.
		// $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
		// $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

		$timestamp = time()."";
		$nonceStr = $this->generateNonceStr();

		// 这里参数的顺序要按照 key 值 ASCII 码升序排序
		$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
		
		$signature = sha1($string);
		
		$signPackage = array(
		  "appId"     => APPID,
		  "nonceStr"  => $nonceStr,
		  "timestamp" => $timestamp,
		  "url"       => $url."/",
		  "signature" => $signature,
		  "rawString" => $string
		);
		return $signPackage; 
	}
	/**
	 * 生成随机字串
	 * @param number $length 长度，默认为16，最长为32字节
	 * @return string
	 */
	public function generateNonceStr($length=32){
		// 密码字符集，可任意添加你需要的字符
		$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
		$str ="";  
		for ( $i = 0; $i < $length; $i++ )  {  
			$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);  
			//$str .= $chars[ mt_rand(0, strlen($chars) - 1) ];  
		}  
		return $str;  
	}

	/**
	 * [发送模板消息]
	 * @param  [array] $data 	[模板消息内容]
	 * @return [array] $res   	[模板消息返回结果]
	 */
	function sendTemplateMessage($data)
	{
		$access_token = $this->getAccessToken();
		$json_template = json_encode($data);
		$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".$access_token;
	    $res = $this->curl->_post($url, urldecode($json_template));
	    return $res;
	}

	/**
	 * [获取微信小程序openid]
	 * @Author   zt
	 * @DateTime 2018-08-13
	 * @return   [type]     [description]
	 */
	function getOpenId($post)
	{
		if (empty($post['js_code'])) {
			return array(
				'code' => 0,
				'msg' => 'js_code参数丢失',
			);	
		}

		$url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.APPID.'&secret='.APPSECRET.'&js_code='.$post['js_code'].'&grant_type=authorization_code';

		$res = json_decode(file_get_contents($url),true);

		if (isset($res['openid'])) {
			$return = array(
				'code' => 1,
				'msg' => 'openid获取成功',
				'open_id' => $res['openid'],
			);
		} else {
			$return = array(
				'code' => 0,
				'msg' => 'openid获取失败',
			);
		}

		return $return;
	}

	/**
	 * [获取小程序二维码]
	 * @Author   zt
	 * @DateTime 2018-08-13
	 * @return   [type]     [description]
	 */
	function getQrCode($post)
	{
		$access_token = $this->getAccessToken();

		$data = array(
			'scene' => $post['scene'],
			'page' => $post['page'],
		);
		$json_data = json_encode($data);

		$url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=".$access_token;

	    $res = $this->_requestPost($url, urldecode($json_data));
	    
	    // 判断文件夹是否存在,不存在则生成文件夹
	    if (!is_dir('static/qrcode/')) {
			mkdir('static/qrcode/', 0777, true);
		}

	    $time = time();
	    file_put_contents("static/qrcode/".$time.".jpg", $res);

	    $return = array(
	    	'name' => $time.'.jpg',
	    	'tmp_name' => "static/qrcode/".$time.".jpg",
	    );

	    return $return;
	}

	/**
	 * [小程序post请求]
	 * @Author   zt
	 * @DateTime 2018-08-13
	 * @param    [type]     $url  [description]
	 * @param    [type]     $data [description]
	 * @param    boolean    $ssl  [description]
	 * @return   [type]           [description]
	 */
	function _requestPost($url, $data, $ssl=true) {
        //curl完成
        $curl = curl_init();
        //设置curl选项
        curl_setopt($curl, CURLOPT_URL, $url);//URL
        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 FirePHP/0.7.4';
        curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);//user_agent，请求代理信息
        curl_setopt($curl, CURLOPT_AUTOREFERER, true);//referer头，请求来源
        curl_setopt($curl, CURLOPT_TIMEOUT, 30);//设置超时时间
        //SSL相关
        if ($ssl) {
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//禁用后cURL将终止从服务端进行验证
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//检查服务器SSL证书中是否存在一个公用名(common name)。
        }
        // 处理post相关选项
        curl_setopt($curl, CURLOPT_POST, true);// 是否为POST请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);// 处理请求数据
        // 处理响应结果
        curl_setopt($curl, CURLOPT_HEADER, false);//是否处理响应头
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);//curl_exec()是否返回响应结果

        // 发出请求
        $response = curl_exec($curl);
        if (false === $response) {
            echo '<br>', curl_error($curl), '<br>';
            return false;
        }
        curl_close($curl);
        return $response;
    }
}
